/**
 * SharedAPIFunctions.java
 * ************************** 
 * @date Apr 19, 2011
 * @author Michele Tamburini
 * 
 * **************************
 */
package infrastructureAPI.backendGate;

import infrastructureAPI.APIMessages.ResponseMessage;
import infrastructureAPI.algorithms.APIFunction;
import infrastructureAPI.backendGate.scriptsResponse.ConcreteResponseReceiverScriptAPI;
import infrastructureAPI.backendGate.scriptsResponse.ResponseReceiverScriptAPI;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.util.List;
import java.util.Vector;

import messages.Message;

/**
 * Description:  
 * The APIRoutineFunctions is an abstract class that can be 
 * used in order to facilitate the implementation of the scripts 
 * that have to call the API features of the cloud. 
 * It's a collection of useful functions.
 */
public abstract class APIRoutineFunctions {
	
	public final static Integer RMIREGISTRY_STADARD_PORT = 1099;
	
	private static RequestMarshalling marshaller = new GeneralSystemsMarshaller();
	private static ResponseReceiverScriptAPI receiver;
//	private static RequestMessageDeliver rmd;
	
	/**
	 * Converts the input argument String[] into a Vector<String>
	 * that can be easily manipulated in order to manger the 
	 * incoming parameters. 
	 */
	public static Vector<String> convertToVector(String[] args){
		Vector<String> vec = new Vector<String>();
		for(String s : args){
			vec.add(s);
		}
		return vec;
	}
	
	/**
	 * Using the GeneralSystemsMarshaller this function builds the
	 * and returns the Message containing the APIFunction in input
	 * and that's directed to the local node denoted by the 
	 * InetAddress and the nodeName.
	 * @param localAddress
	 * @param localNodeName
	 * @param apiFunc
	 * @return message : Message
	 */
	public static Message marshal(InetAddress localAddress, 
			String localNodeName, APIFunction apiFunc){
		return marshaller.marshalRequest(localAddress, 
				localNodeName, apiFunc);
	}
	
	/**
	 * Delivers the input Message 'msg' to the node denoted by the
	 * 'nodeName'.
	 * @param msg
	 * @param nodeName
	 * @return done : boolean
	 */
	public static boolean deliverMessage(Message msg, String nodeName){
		boolean ret = false;
		RequestMessageDeliver rmd;
		try {
			rmd = new GeneralRequestMessageDeliver();
			ret = rmd.deliver(msg, nodeName);
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			e.printStackTrace();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
		return ret;
	}

	/**
	 * This procedure counts the number of parameters excluding
	 * any input option. 
	 * Because the option name begins with a '-' 
	 * the algorithm simply subtract -1 for each string beginning
	 * with a '-' and add +1 for each string without a '-'
	 * character. 
	 * Please be careful to the parameters and options composition.
	 * 
	 * @param arguments
	 * @return numberOfParameters : int
	 */
	public static int extractParametersNumber(List<String> arguments) {
		int ret = 0;
		for(String s: arguments){
			if(s.contains("-")){
				ret--;
			}else{
				ret++;
			}
		}
		return ret;
	}
	
	/**
	 * The ResponseAPIReceiver class is responsible to manage the 
	 * incoming messages from the cloud that represent the replies
	 * to a request submitted before. 
	 * This function allocates a ResponseAPIReceiver and registers 
	 * the current script to the local rmiregistry.
	 * @param address
	 * @param registeredService
	 * @return done : boolean
	 * @throws UnknownHostException
	 * @throws RemoteException
	 */
	public static boolean initializeResponseReceiver(InetAddress address, String registeredService) 
		throws UnknownHostException, RemoteException{
		receiver = new ConcreteResponseReceiverScriptAPI(address, registeredService);
		return true;
	}
	
	/**
	 * It return a ResponseMessage once.
	 * @return response : ResponseMessage
	 * @throws RemoteException 
	 */
	public static ResponseMessage receiveResponse(){
		return  receiver.waitForResponseMessage();	
	}
	
	public static boolean disconnectReceiver(){
		return receiver.terminate();
	}
	

}
